<template>
  <el-card>
    <el-form class="form" ref="form" :inline="true" label-width="80px">
      <el-form-item label="角色搜索">
        <el-input v-model="roleValue" placeholder="请输入要搜索的角色名"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" :disabled="!roleValue" @click="searchRole"
          >搜素</el-button
        >
        <el-button type="default" @click="resetInfo">重置</el-button>
      </el-form-item>
    </el-form>
  </el-card>
  <el-card style="margin: 10px 0px">
    <el-button
      type="primary"
      icon="Plus"
      @click="addRole"
      v-auth-buttons="'role.button.add'"
      >添加角色</el-button
    >
    <el-table :data="roleList" style="margin: 10px 0px" border>
      <el-table-column type="index" align="center" label="#" width="80px">
      </el-table-column>
      <el-table-column prop="id" align="center" label="ID" width="80px">
      </el-table-column>
      <el-table-column prop="roleName" label="角色名称" align="center"> </el-table-column>
      <el-table-column
        prop="createTime"
        show-overflow-tooltip
        label="创建时间"
        align="center"
      >
      </el-table-column>
      <el-table-column
        prop="updateTime"
        show-overflow-tooltip
        label="更新时间"
        align="center"
      >
      </el-table-column>
      <el-table-column label="操作" width="280px" align="center">
        <template #="{ row }">
          <el-button type="primary" size="small" icon="User" @click="assignAuth(row)"
            >分配权限</el-button
          >
          <el-button type="warning" size="small" icon="Edit" @click="editRole(row)"
            >编辑</el-button
          >
          <el-popconfirm
            :title="`确定删除角色【${row.roleName}】吗`"
            width="240px"
            @confirm="deleteRole(row)"
          >
            <template #reference>
              <el-button type="danger" size="small" icon="Delete">删除</el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页器 -->
    <el-pagination
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      background
      :page-sizes="[5, 10, 20]"
      layout="->, prev, pager, next, sizes, jumper, total"
      :total="total"
      @current-change="curPageChange"
      @size-change="pageSizeChange"
    >
    </el-pagination>
  </el-card>
  <!-- 对话框：新增或修改角色 -->
  <el-dialog
    :title="roleFormData.id ? '修改角色' : '添加角色'"
    width="600px"
    v-model="dialogVisible"
  >
    <el-form ref="formRef" :model="roleFormData" :rules="rules">
      <el-form-item prop="roleName" label="角色名称">
        <el-input v-model="roleFormData.roleName"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="dialogVisible = false">取 消</el-button>
      <el-button type="primary" @click="saveRole">确 定</el-button>
    </template>
  </el-dialog>
  <!-- 抽屉组件：分配角色权限 -->
  <el-drawer v-model="drawerVisible">
    <template #header>
      <h1>分配权限</h1>
    </template>
    <template #default>
      <el-tree
        v-loading="loading"
        element-loading-text="加载中"
        ref="treeRef"
        :data="userDataPermission"
        :props="defaultProps"
        show-checkbox
        node-key="id"
        default-expand-all
        :default-checked-keys="checkMenuButton"
      ></el-tree>
    </template>
    <template #footer>
      <el-button type="primary" @click="saveRolePermission">确定</el-button>
      <el-button type="default" @click="drawerVisible = false">取消</el-button>
    </template>
  </el-drawer>
</template>

<script setup lang="ts">
import {
  reqAddRole,
  reqEditRole,
  reqDataPermission,
  reqDeleteRole,
  reqSaveRolePermission,
  reqUserRole,
} from "@/api/acl/role";
import {
  DataPermissionResData,
  MenuButtonDataObj,
  RoleObj,
  RoleResData,
} from "@/api/acl/role/types";
import { ElMessage } from "element-plus";
import { ref, onMounted, nextTick } from "vue";
import { useLayoutSettingStore } from "@/store/modules/setting";
// 获取配置对象
const settingStore = useLayoutSettingStore();
// 当前页
const currentPage = ref(1);
// 页面显示页面条数
const pageSize = ref(5);
// 数据总数
const total = ref(0);
// 角色信息
const roleList = ref<RoleObj[]>([]);
// 搜索框的值
const roleValue = ref("");
// 控制对话框的显示和隐藏
const dialogVisible = ref(false);
// 新增或修改表单数据
const roleFormData = ref<RoleObj>({
  roleName: "",
});
// 角色名的校验
const roleNameValid = (rule: any, value: any, callback: any) => {
  if (value.trim()) {
    callback();
  } else {
    callback(new Error("用户名不能为空"));
  }
};
// 表单校验
const rules = ref({
  roleName: [{ required: true, trigger: "blur", validator: roleNameValid }],
});
// form表单实例
const formRef = ref();
// 控制抽屉的显示和隐藏
const drawerVisible = ref(false);
// 属性组件的加载状态
const loading = ref(false);
// 存储用户的数据权限
const userDataPermission = ref<MenuButtonDataObj[]>([]);
// 配置树形组件的数据结构，告诉树形组件如何从数据中读取节点的关键属性
const defaultProps = {
  children: "children",
  label: "name",
};
// 存储已勾选的最低层的菜单或按钮的id
const checkMenuButton = ref<number[]>([]);
// 树形组件实例
const treeRef = ref();
// 页面渲染完毕，获取数据
onMounted(() => {
  getRoleList();
});
// 获取角色信息
const getRoleList = async (curPage = 1) => {
  // 修改当前页的原因：页面大小发生变化时，需要将当前页变为1
  currentPage.value = curPage;
  let result: RoleResData = await reqUserRole(
    currentPage.value,
    pageSize.value,
    roleValue.value
  );
  if (result?.code === 200) {
    roleList.value = result.data?.records;
    total.value = result.data?.total;
  } else {
    ElMessage.error("角色信息获取失败");
  }
};
// 当前页改变事件回调
const curPageChange = () => {
  getRoleList(currentPage.value);
};
// 页面显示条数改变事件回调
const pageSizeChange = () => {
  getRoleList();
};
// 搜索按钮回调
const searchRole = () => {
  getRoleList();
};
// 重置按钮回调
const resetInfo = () => {
  (roleValue.value = ""), getRoleList();
};
// 添加角色按钮回调
const addRole = () => {
  // 打开对话框
  dialogVisible.value = true;
  // 清空缓存数据
  roleFormData.value = {
    roleName: "",
  };
  // 页面渲染完毕后，清空表单提示信息
  nextTick(() => {
    formRef.value.clearValidate("roleName");
  });
};
// 编辑角色按钮回调
const editRole = (row: RoleObj) => {
  // 打开对话框
  dialogVisible.value = true;
  // 数据回显
  roleFormData.value = JSON.parse(JSON.stringify(row));
  // 页面渲染完毕后，清空表单提示信息
  nextTick(() => {
    formRef.value.clearValidate("roleName");
  });
};
// 对话框的确定按钮回调
const saveRole = () => {
  formRef.value.validate(async (valid: boolean) => {
    if (valid) {
      // 表单验证通过
      if (roleFormData.value.id) {
        // 存在id，修改角色信息
        let result = await reqEditRole(roleFormData.value);
        if (result?.code === 200) {
          ElMessage.success("角色修改成功");
          dialogVisible.value = false;
          // 重新获取数据
          getRoleList(currentPage.value);
        } else {
          ElMessage.error("角色修改失败");
          dialogVisible.value = false;
        }
      } else {
        // 不存在id，新增角色信息
        let result = await reqAddRole(roleFormData.value);
        if (result?.code === 200) {
          ElMessage.success("角色新增成功");
          dialogVisible.value = false;
          // 重新获取数据
          getRoleList(roleFormData.value.id ? currentPage.value : 1);
        } else {
          ElMessage.error("角色新增失败");
          dialogVisible.value = false;
        }
      }
    }
  });
};
// 删除角色按钮回调
const deleteRole = async (row: RoleObj) => {
  // 发送请求删除某个角色
  let result: any = await reqDeleteRole(row.id as number);
  if (result?.code === 200) {
    ElMessage.success("角色删除成功");
    // 重新获取数据
    if (roleList.value.length > 1) {
      // 当前页数据大于一条，删除后留在当前页
      getRoleList(currentPage.value);
    } else {
      // 当前页数据小于一条
      if (currentPage.value === 1) {
        // 当前页是第一页，删除后留在当前页
        getRoleList(currentPage.value);
      } else {
        // 当前页不是第一页，删除后去往上一页
        getRoleList(currentPage.value - 1);
      }
    }
  } else {
    ElMessage.error("角色删除失败");
  }
};
// 分配权限按钮回调
const assignAuth = async (row: RoleObj) => {
  // 打开抽屉
  drawerVisible.value = true;
  // 开启加载
  loading.value = true;
  // 存储当前角色的信息，方便保存权限时使用
  roleFormData.value = row;
  // 发送请求获取当前角色的数据权限
  let result: DataPermissionResData = await reqDataPermission(row.id as number);
  if (result?.code === 200) {
    userDataPermission.value = result?.data;
    // 过滤数组，选择已选择的最底层的菜单或按钮的id
    checkMenuButton.value = filterSelectdArr(userDataPermission.value, []);
    nextTick(() => {
      loading.value = false;
    });
    console.log("已选择的菜单或按钮的id", checkMenuButton.value);
  } else {
    ElMessage.error("数据权限获取失败");
  }
};
// 递归方法：遍历出已勾选的最底层的菜单或按钮的id
const filterSelectdArr = (dataArr: MenuButtonDataObj[], initArr: number[]) => {
  dataArr.forEach((item) => {
    if (item.children && item.children.length > 0) {
      // 若有孩子，则递归
      filterSelectdArr(item.children, initArr);
    } else {
      // 没有孩子时执行，判断是否选中
      if (item.select) {
        initArr.push(item.id);
      }
    }
  });
  return initArr;
};
// 抽屉中确定按钮的回调
const saveRolePermission = async () => {
  // 关闭抽屉
  drawerVisible.value = false;

  // 选中的元素id
  const checkedId: number[] = treeRef.value.getCheckedKeys();
  console.log("当前选中的元素id", checkedId);

  // 半选中的元素id
  const halfCheckedId: number[] = treeRef.value.getHalfCheckedKeys();
  console.log("当前半选中的元素id", halfCheckedId);

  // 发送请求保存权限信息
  let result: any = await reqSaveRolePermission({
    roleId: roleFormData.value.id as number,
    permissionIdList: checkedId.concat(halfCheckedId),
  });
  if (result?.code === 200) {
    // 给出提示
    ElMessage.success("分配权限成功");
    // 若自己将自己的权限修改没了，就不能访问页面了，需要刷新页面
    settingStore.isRefresh = true;
  } else {
    ElMessage.error("分配权限失败");
  }
};
</script>

<style scoped lang="scss">
.form {
  display: flex;
  justify-content: space-between;
  .el-form-item {
    margin-bottom: 0px;
  }
}
</style>
